/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */package org.merak.core.text.json;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.merak.core.text.json.annotation.JsonDate;
import org.merak.core.text.json.annotation.JsonSkip;
import org.merak.core.text.json.jsonfiers.DateFormatJsonfier;
import org.merak.core.text.json.jsonfiers.Jsonfier;

public final class TemplateObject {

    //~ Attributes ///////////////////////////////////////////////////////////////
	//****************************************************************************
	private TemplateProperty[] getters = null;
	private TemplateProperty[] setters = new TemplateProperty[0];

    //~ Constructors /////////////////////////////////////////////////////////////
	//****************************************************************************
	protected TemplateObject(Object object) {

		Class<?> clazz = object.getClass();
		while ( clazz.getSimpleName().contains("$") && clazz.getSuperclass()!=null) {
			clazz = clazz.getSuperclass();
		}
		this.getters = discoverGetters(clazz);
	}

    //~ Methods //////////////////////////////////////////////////////////////////
	//****************************************************************************
	private static TemplateProperty[] discoverGetters(Class<?> clazz) {

		List<TemplateProperty> list = new ArrayList<TemplateProperty>();
		String  name = null;

		// Select all getter method
		for (Method m : clazz.getMethods()) {
			// Ignore the method if annotated with JsonSkip
			if (m.isAnnotationPresent(JsonSkip.class)) continue;

			// Ignore the method if returns Nothing or Class object
			if (Class.class.isAssignableFrom(m.getReturnType())) continue;
			if (Void.class.isAssignableFrom(m.getReturnType())) continue;

			// Ignore the method if not a getter
			if (m.getParameterTypes().length > 0) continue; // must have no params
			if (!m.getName().startsWith("get")  ) continue; // must have prefix "get"
			if (m.getName().length() < 4        ) continue; // must have a word after "get"

            // Format the attribute's name
            name = Character.toLowerCase(m.getName().charAt(3)) + m.getName().substring(4);
            
            // Create a template for this method
            TemplateProperty template = new TemplateProperty(name,m,null);
            list.add(template);

            // Check format annotations
            JsonDate jsonDate = m.getAnnotation(JsonDate.class);         
            if (jsonDate != null) {
            	Jsonfier jsonfier = null;
            	if (!jsonDate.dateStyle().isUnknown() || !jsonDate.timeStyle().isUnknown()) {
            		jsonfier = new DateFormatJsonfier(jsonDate.dateStyle(),jsonDate.timeStyle());
            	}
            	else {
            		jsonfier = new DateFormatJsonfier(jsonDate.format());
            	}
            	template.setJsonfier(jsonfier);
            }
		}

		// Convert the list into an array
		return list.toArray( new TemplateProperty[list.size()] );

	}
	//****************************************************************************
	public final TemplateProperty[] getGettableAttributes() {
		return this.getters;
	}
	//****************************************************************************
	public final TemplateProperty[] getSettableAttributes() {
		return this.setters;
	}
	//****************************************************************************
	public final boolean hasGetters() {
		return this.getters.length != 0;
	}
	//****************************************************************************
	public final boolean hasSetters() {
		return this.setters.length != 0;
	}
	//****************************************************************************
	public final boolean notHasGetters() {
		return this.getters.length == 0;
	}
	//****************************************************************************
	public final boolean notHasSetters() {
		return this.setters.length == 0;
	}
	//****************************************************************************

}
